<?php

namespace Phoo\db;

require_once "db/query.php";
require_once "db/string_property.php";
require_once "db/integer_property.php";

require_once "db/errors/not_saved_error.php";
require_once "db/errors/bad_value_error.php";

abstract class Model {
	private static $db = null;
	
    private $data = array();
    private $id = null;
    
    public final function __construct($values = array()){
    	$this->create();
    	
    	$fields = get_object_vars($this);
    	
    	foreach($fields as $name => $value){
    		if($value instanceof Property){
    			$this->data[$name] = $value;
    			unset($this->$name);
    		}
    	}
    	
    	foreach($values as $name => $value){
    		if($name == "_id")
    			$this->id = $value;
    		else
    			$this->$name = $value;
    	}
    	
    	foreach($this->data as $name => $property){
    		if($property->isRequired() && $property->getValue() === null)
    			throw new BadValueError();
    	}
    }
    
    abstract protected function create();
    
	public final function __set($name, $value) {
		if($value instanceof Property)
			$this->data[$name] = $value;
		else if(array_key_exists($name,$this->data))
			$this->data[$name]->setValue($value);
		else
			$this->$name = $value;
			
		return $value;
    }
    
	public final function __get($name) {
        if (array_key_exists($name, $this->data))
            return $this->data[$name]->getValue();
        
        return null;
    }

    public final function __isset($name) {
        return isset($this->data[$name]);
    }

    public final function __unset($name) {
        unset($this->data[$name]);
    }
    
    private static function db(){
    	if(self::$db === null){
    		$className = get_called_class();
    		$db = new \Mongo("mongodb://{$_ENV["DB_USER"]}:{$_ENV["DB_PASSWORD"]}@localhost/{$_ENV["SITE"]}");
    		self::$db = $db->$_ENV["SITE"]->$className;
    	}
    	
    	return self::$db;
    }
    
    public final function delete(){
    	$db = self::db();
    	if($this->key() === null)
    		throw new NotSavedError();
    	return $db->remove(array('_id' => $this->key()),true);
    }
    
    public final function key(){
    	return $this->id;
    }
    
    public final function put(){
    	$db = self::db();
    	$data = array();
    	foreach($this->data as $name => $value){
    		$data[$name] = $value->getValue();
    	}
    	$db->save($data);
    	$this->id = $data['_id'];
    }
    
    public static function all(){
    	$db = self::db();
    	return new Query($db,get_called_class());
    }
}